import {Component, Input, OnInit} from '@angular/core';
import Feature from 'ol/Feature.js';
import Map from 'ol/Map.js';
import {unByKey} from 'ol/Observable.js';
import View from 'ol/View.js';
import {easeOut} from 'ol/easing.js';
import Point from 'ol/geom/Point.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';
import {fromLonLat} from 'ol/proj.js';
import {OSM, Vector as VectorSource} from 'ol/source.js';
import {Circle as CircleStyle, Stroke, Style} from 'ol/style.js';
import {UtilComponent} from '../../interface/util-component.interface';
import XYZ from 'ol/source/XYZ';

@Component({
    selector: 'kylin-custom-animation',
    templateUrl: './custom-animation.component.html',
    styleUrls: ['./custom-animation.component.less']
})
export class CustomAnimationComponent implements OnInit, UtilComponent {
    // ---------- 接口实现 begin -------------- //
    hasContent = true;
    map: Map;

    @Input() set data(val) {
        Object.assign(this, val);
    };

    // ---------- 接口实现 end ---------------- //
    vectorSource: VectorSource;
    vectorLayer: VectorLayer;
    duration = 3000;
    originView: any;
    timer: any;
    topographicLayer: TileLayer;
    operationStr = '开始';

    constructor() {
    }

    ngOnInit() {
        this.turnOn();
    }

    turnOn() {

        this.vectorSource = new VectorSource({
            wrapX: false
        });
        this.vectorLayer = new VectorLayer({
            source: this.vectorSource
        });

        this.topographicLayer = new TileLayer({
            source: new XYZ({
                url: 'http://www.google.cn/maps/vt/pb=!1m4!1m3!1i{z}!2i{x}!3i{y}!2m3!1e0!2sm!3i380072576!3m8!2szh-CN!3scn!5e1105!12m4!1e68!2m2!1sset!2sRoadmap!4e0!5m1!1e0'
            })
        });

        this.map.addLayer(this.topographicLayer);
        this.map.addLayer(this.vectorLayer);

        const view = this.map.getView();
        this.originView = {
            center: view.getCenter(),
            zoom: view.getZoom()
        };
        view.setCenter([0, 0]);
        view.setZoom(1);

        this.vectorSource.on('addfeature', (e) => {
            this.flash(e.feature);
        });
    }

    addRandomFeature = () => {
        const x = Math.random() * 360 - 180;
        const y = Math.random() * 180 - 90;
        const geom = new Point(fromLonLat([x, y], 'EPSG:3857'));
        const feature = new Feature(geom);
        this.vectorSource.addFeature(feature);
    }

    flash(feature) {
        const start = new Date().getTime();

        const animate = (event) => {
            const vectorContext = event.vectorContext;
            const frameState = event.frameState;
            const flashGeom = feature.getGeometry().clone();
            const elapsed = frameState.time - start;
            const elapsedRatio = elapsed / this.duration;
            // radius will be 5 at start and 30 at end.
            const radius = easeOut(elapsedRatio) * 25 + 5;
            const opacity = easeOut(1 - elapsedRatio);

            const style = new Style({
                image: new CircleStyle({
                    radius: radius,
                    stroke: new Stroke({
                        color: 'rgba(255, 0, 0, ' + opacity + ')',
                        width: 0.25 + opacity
                    })
                })
            });

            vectorContext.setStyle(style);
            vectorContext.drawGeometry(flashGeom);
            if (elapsed > this.duration) {
                unByKey(listenerKey);
                return;
            }
            // tell OpenLayers to continue postcompose animation
            this.map.render();
        }
        const listenerKey = this.map.on('postcompose', animate);
    }

    turnOff() {
        this.map.removeLayer(this.vectorLayer);
        this.map.removeLayer(this.topographicLayer);
        if (this.originView) {
            this.map.getView().setZoom(this.originView.zoom);
            this.map.getView().setCenter(this.originView.center);
        }
        if (this.timer) {
            window.clearInterval(this.timer);
        }
    }

    cancel(options?: any): any {
        this.turnOff();
    }

    toggleOperation() {
        if (this.timer) {
            window.clearInterval(this.timer);
            this.operationStr = '开始';
            this.timer = null;
        } else {
            this.timer = window.setInterval(this.addRandomFeature, 1000);
            this.operationStr = '暂停';
        }
    }
}
